package com.bonorsoft.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.bonorsoft.common.api.Result;
import com.bonorsoft.common.api.WilliamBootException;
import com.bonorsoft.config.MyConfig;
import com.bonorsoft.system.entity.SysMoney;
import com.bonorsoft.system.entity.SysSet;
import com.bonorsoft.system.mapper.SysMoneyMapper;
import com.bonorsoft.system.service.SysMoneyService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bonorsoft.util.HttpRequest;
import com.bonorsoft.util.IPUtils;
import com.bonorsoft.system.sdk.WXPayUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author WilliamYe
 * @since 2020-07-23
 */
@Service
@Transactional
public class SysMoneyServiceImpl extends ServiceImpl<SysMoneyMapper, SysMoney> implements SysMoneyService {

    /**
     * 缴费
     * @param money
     * @param request
     * @return
     */
    @Override
    public Result<?> wxPay(SysMoney money, HttpServletRequest request) {
        String openId = money.getOpenid();
        String no = new SimpleDateFormat("yyyyMMdd").format(new Date()) + new Date().getTime();
        money.setOutTradeNo(no);
        money.setDate(new Date());
        super.save(money);

        //库存变化
        //Integer subStroge = stroge - 1;
        int count = this.baseMapper.subStroge();
        if (count <= 0){
            throw new WilliamBootException("支付失败, 报名名额已满！");
        }
        //请求微信小程序支付接口
        try {
            // 拼接统一下单地址参数
            Map<String, String> paraMap = new HashMap<String, String>();
            // 获取请求ip地址
            String ip = IPUtils.getIpAddr(request);
            MyConfig config = new MyConfig();
            paraMap.put("appid", config.getAppID()); // 商家平台ID
            paraMap.put("body", config.getMchName()); // 商家名称-销售商品类目、String(128)
            paraMap.put("mch_id", config.getMchID()); // 商户ID
            paraMap.put("nonce_str", WXPayUtil.generateNonceStr()); // UUID
            paraMap.put("openid", openId);
            paraMap.put("out_trade_no", no);// 订单号,每次都不同
            paraMap.put("spbill_create_ip", ip);
            paraMap.put("total_fee", money.getMoney()); // 支付金额，单位分
            paraMap.put("trade_type", "JSAPI"); // 支付类型
            paraMap.put("notify_url", "https://pay.cht.com.cn/wxpay/notify");// 此路径是微信服务器调用支付结果通知路径随意写
            String sign = WXPayUtil.generateSignature(paraMap, config.getKey());
            paraMap.put("sign", sign);
            String xml = WXPayUtil.mapToXml(paraMap);// 将所有参数(map)转xml格式
            // 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder
            String unifiedorder_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
            System.out.println("xml为：" + xml);
            // String xmlStr = HttpRequest.sendPost(unifiedorder_url,
            // xml);//发送post请求"统一下单接口"返回预支付id:prepay_id
            String xmlStr = HttpRequest.httpsRequest(unifiedorder_url, "POST", xml);
            System.out.println("xmlStr为：" + xmlStr);
            this.baseMapper.insertCallBck(no, xmlStr);
            // 以下内容是返回前端页面的json数据
            String prepay_id = "";// 预支付id
            if (xmlStr.contains("SUCCESS")) {
                Map<String, String> map = WXPayUtil.xmlToMap(xmlStr);
                prepay_id = map.get("prepay_id");
            }

            Map<String, String> payMap = new HashMap<String, String>();
            payMap.put("appId", config.getAppID());
            payMap.put("timeStamp", WXPayUtil.getCurrentTimestamp() + "");
            payMap.put("nonceStr", WXPayUtil.generateNonceStr());
            payMap.put("signType", "MD5");
            payMap.put("package", "prepay_id=" + prepay_id);
            String paySign = WXPayUtil.generateSignature(payMap, config.getKey());
            payMap.put("paySign", paySign);
            payMap.put("openid", openId);
            payMap.put("outTradeNo", no);
            //将这个6个参数传给前端
            return Result.ok(payMap);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("支付失败！");
        }
    }

    /**
     * 订单支付完成后根据openid和订单号对订单进行操作
     * @param openid
     * @param ordersSn
     */
    @Override
    public void updateStatusBySql(String openid, String ordersSn) {
        //update sys_money m, (select max(sequence) + 1 max from sys_money) mm set m.pay_status = '1', m.pay_time = NOW(), m.sequence = IFNULL(mm.max,1) where m.openid = '111' and m.out_trade_no = '202108251629884783575'
        this.baseMapper.updateStatusBySql(openid, ordersSn);
    }

    /**
     * 取消订单改变库存
     * @param openid
     * @param outTradeNo
     */
    @Override
    public void cancelOrder(String openid, String outTradeNo) {
        //修改值
        SysMoney noney = new SysMoney();
        noney.setPayStatus("2");
        noney.setCloseTime(new Date());

        //修改条件s
        UpdateWrapper<SysMoney> mUpdateWrapper = new UpdateWrapper<>();
        mUpdateWrapper.eq("openid", openid).eq("out_trade_no",outTradeNo);

        this.update(noney, mUpdateWrapper);

        this.baseMapper.addStroge();
    }

    /**
     * 根据openid判断用户是否已经缴费
     * @param openid
     * @return
     */
    @Override
    public SysMoney paymentConditions(String openid) {
        SysMoney mon = null;
        QueryWrapper<SysMoney> sysMoneyQueryWrapper = new QueryWrapper<>();
        sysMoneyQueryWrapper.eq("openid",openid);
        List<SysMoney> list = this.list(sysMoneyQueryWrapper);
        if(list.size() > 0){
            for (SysMoney money:list) {
                if("1".equals(money.getPayStatus())){
                    mon = money;
                }
            }
        }
        return mon;
    }

    /**
     * 判断支付人数是否已经满了
     * @return
     */
    @Override
    public boolean peopleFull() {
        QueryWrapper<SysMoney> sysMoneyQueryWrapper = new QueryWrapper<>();
        sysMoneyQueryWrapper.eq("pay_status","1");
        int count = this.count(sysMoneyQueryWrapper);
        Integer top = this.baseMapper.getTop();
        return count == top;
    }

    @Override
    public SysSet getBasic() {
        return this.baseMapper.getBasic();
    }

    @Override
    public void saveBasic(SysSet basic) {
        String id = UUID.randomUUID().toString().replaceAll("-", "");
        Date startTime = basic.getStartTime();
        Date endTime = basic.getEndTime();
        this.baseMapper.saveBasic(id,startTime,endTime);
    }

    @Override
    public void updateBasicById(SysSet basic) {
        String id = basic.getId();
        Date startTime = basic.getStartTime();
        Date endTime = basic.getEndTime();
        this.baseMapper.updateBasicById(id,startTime,endTime);
    }

    @Override
    public void updateStroge(Integer sheng) {
        this.baseMapper.upateStroge(sheng);
    }

    /**
     * 获取课程金额
     * @return
     */
    @Override
    public String getMoney() {
        return this.baseMapper.getMoney();
    }

    /**
     * 获取库存
     * @return
     */
    @Override
    public Integer getStroge() {
        return this.baseMapper.getStroge();
    }

    /**
     * 减少库存
     * @param subStroge
     */
    @Override
    public void subStroge(Integer subStroge) {
        this.baseMapper.subStroge();
    }

    /**
     * 订单支付完成后操作，摒弃
     * @param openid
     * @param ordersSn
     */
    @Override
    public void updateStatus(String openid, String ordersSn) {
        //修改值
        SysMoney noney = new SysMoney();
        noney.setPayStatus("1");
        noney.setPayTime(new Date());
        //修改条件s
        UpdateWrapper<SysMoney> mUpdateWrapper = new UpdateWrapper<>();
        mUpdateWrapper.eq("openid", openid).eq("out_trade_no",ordersSn);

        this.myupdate(noney, mUpdateWrapper);

        QueryWrapper<SysMoney> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("openid", openid).eq("out_trade_no",ordersSn);
        SysMoney one = this.getOne(queryWrapper);

        if(one.getSequence() == null){
            one.setSequence(1);
            this.updateById(one);
        }

    }

    /**
     * 修改订单状态
     * @param money
     * @param mUpdateWrapper
     */
    private void myupdate(SysMoney money, UpdateWrapper<SysMoney> mUpdateWrapper) {
        this.baseMapper.myupdate(money,mUpdateWrapper);
    }

}
